%{
	
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "symbol.h"
#include "type_name_stack.h"
#include "operator_stack.h"
#include "def_all_functions.h"
#include "def_additive_expression.h"
#include "def_argument_expression_list.h"
#include "def_comparison_expression.h"
#include "def_compound_statement.h"
#include "def_declaration.h"
#include "def_declaration_list.h"
#include "def_declarator.h"
#include "def_declarator_list.h"
#include "def_expression.h"
#include "def_expression_statement.h"
#include "def_external_declaration.h"
#include "def_function_definition.h"
#include "def_iteration_statement.h"
#include "def_jump_statement.h"
#include "def_multiplicative_expression.h"
#include "def_parameter_declaration.h"
#include "def_parameter_list.h"
#include "def_postfixe_expression.h"
#include "def_primary_expression.h"
#include "def_program.h"
#include "def_selection_statement.h"
#include "def_statement.h"
#include "def_statement_list.h"
#include "def_unary_expression.h"
	
	
	struct table_symbol{
		struct symbol * symbols[255];
		int count;
	};
	struct stack_table_symbol{
		struct table_symbol stack[2];
		int count;
	};
	
	void table_symbol_init(struct table_symbol * t){
		t->count=0;
	}
	void table_symbol_free(struct table_symbol * t){
		int i=0;
		for(;i<t->count;i++){
			symbol_free(t->symbols[i]);
		}
		t->count = 0;
	}

	
	void table_symbol_add(struct table_symbol * t, struct symbol * s){
		t->symbols[t->count] = s;
		t->count++;
	}
	int table_symbol_has(struct table_symbol * t, const char * s){
		int i;
		for(i=t->count-1;i>=0;i--){
			if(strcmp(t->symbols[i]->_name, s) == 0)
				return 1;
		}
		return 0;
	}
	
	struct table_symbol _external_table;
	struct table_symbol _temporary_table;
	int _temporary_table_init = 0;
	
	void external_table_print(){
		int i;
		printf("EXTERNAL\n");
		for(i=0;i<_external_table.count;i++)
			symbol_print(_external_table.symbols[i]);
	}
	void temporary_table_print(){
		int i;
		printf("TEMPORARY\n");
		for(i=0;i<_temporary_table.count;i++)
			symbol_print(_temporary_table.symbols[i]);
	}
	void external_table_init(){
		table_symbol_init(&(_external_table));
	}
	
	void temporary_table_add(struct symbol * s){
		_temporary_table.symbols[_temporary_table.count] = s;
		_temporary_table.count++;
	}
	void external_table_add(struct symbol * s){
		_external_table.symbols[_external_table.count] = s;
		_external_table.count++;
	}
	
	void temporary_table_init(){
		_temporary_table_init = 1;
		table_symbol_init(&(_temporary_table));
	}
	int external_table_has(char *s){
		return table_symbol_has(&_external_table, s);
	}
	int temporary_table_has(char * s){
		printf("\ntrying to search %s\n",s);
		if(table_symbol_has(&_temporary_table, s) == 1){
			return 1;
		}
		return external_table_has(s);
	}
	int temporary_table_has_function(){
		int i=0;
		for(;i<_temporary_table.count;i++){
			if(symbol_get_mode(_temporary_table.symbols[i]) == MODE_FUNCTION)
				return 1;
		}
		return 0;
	}
	
	int temporary_table_delete(char * s){
		int i;
		for(i=_temporary_table.count-1;i>=0;i--){
			if(strcmp(_temporary_table.symbols[i]->_name, s) == 0){
				if(_temporary_table.count > 1 && i != _temporary_table.count-1){
					_temporary_table.symbols[i] = _temporary_table.symbols[_temporary_table.count-1];
				}
				_temporary_table.count--;
			}
		}
				 return 1;
	}
	int is_temporary_table_init(){
		return _temporary_table_init == 1;
	}
	int table_symbol_has_function(){
		return _temporary_table.count > 0;
	}
	void temporary_table_deinit(){
		temporary_table_init();
		_temporary_table_init = 0;
	}

	extern int yylineno;
	int yylex ();
	int yyerror ();
	
	%}

%token <str> IDENTIFIER CONSTANT
%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
%token SUB_ASSIGN MUL_ASSIGN ADD_ASSIGN
%token TYPE_NAME
%token INT FLOAT VOID
%token IF ELSE WHILE RETURN FOR
%union {
	char *str;
	void *ret;
	struct def_argument_expression_list * argument_expression_list;
}

%type<argument_expression_list> argument_expression_list
%type<ret> postfix_expression unary_operator primary_expression expression unary_expression multiplicative_expression comparison_expression additive_expression assignment_operator declarator_list type_name parameter_list parameter_declaration declarator statement compound_statement expression_statement selection_statement iteration_statement jump_statement statement_list declaration_list declaration program external_declaration function_definition
%start program
%%

//done
primary_expression
: IDENTIFIER {printf("primary_expression IDENTIFIER\n");
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 1;
	p->identifier = $1;
	$$=p;
}
| CONSTANT {printf("primary_expression CONSTANT\n"	);
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 2;
	p->constant = $1;
	$$=p;
}
| '(' expression ')' {printf("primary_expression (expression)\n");
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 3;
	p->expression = $2;
	$$=p;
}
| IDENTIFIER '(' ')' {printf("primary_expression IDENTIFIER ()\n");
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 4;
	p->identifier = $1;
	$$=p;
}
| IDENTIFIER '(' argument_expression_list ')' {printf("primary_expression IDENTIFIER (argument expression list)\n");;
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 5;
	p->identifier = $1;
	p->argument_expression_list = $3;
	printf("valeur affichee par l'expression liste %d\n",p->argument_expression_list->type);
	argument_expression_list_print($3);
	$$=p;
}
| IDENTIFIER INC_OP {printf("primary_expression IDENTIFIER INC OP\n");;
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 6;
	p->identifier = $1;
	$$=p;
}
| IDENTIFIER DEC_OP {printf("primary_expression IDENTIFIER DEC OP\n");;
	struct def_primary_expression * p = primary_expression_create(NULL);
	p->type = 7;
	p->identifier = $1;
	$$=p;
}
;

//done
postfix_expression
: primary_expression {printf("postfix_expression primary_expression\n");
	struct def_postfixe_expression * p = postfixe_expression_create(NULL);
	p->type = 1;
	p->primary_expression = $1;
	$$=p;
}
| postfix_expression '[' expression ']' {printf("postfix_expression postfix_expression\n");
	struct def_postfixe_expression * p = postfixe_expression_create(NULL);
	p->type = 2;
	p->postfixe_expression = $1;
	p->expression = $3;
	$$=p;}
;

//done
argument_expression_list
: expression {printf("argument_expression_list expression\n");
	struct def_argument_expression_list * p = argument_expression_list_create(NULL);
	p->type = 1;
	p->expression = $1;
	$$=p;
}
| argument_expression_list ',' expression {printf("argument_expression_list argument_expression_list\n");
	struct def_argument_expression_list * p = argument_expression_list_create(NULL);
	p->type = 2;
	p->expression = $3;
	if($1 == NULL)
		return 1;
	p->argument_expression_list = $1;
	$$=p;
}
;

//done
unary_expression
: postfix_expression {printf("unary_expression postfixe_expression\n");
	struct def_unary_expression *s = unary_expression_create(NULL);
	s->type = 1;
	s->postfix_expression = $1;
	$$=s;
}
| INC_OP unary_expression {printf("unary_expression INC OP unarty expression\n");
	struct def_unary_expression *s = unary_expression_create(NULL);
	s->type = 2;
	s->unary_expression = $2;
	$$=s;
}
| DEC_OP unary_expression {printf("unary_expression DEC OP unary expression\n");
	struct def_unary_expression *s = unary_expression_create(NULL);
	s->type = 3;
	s->unary_expression = $2;
	$$=s;
}
| unary_operator unary_expression {printf("unary_expression unary expression unexary expression\n");
	struct def_unary_expression *s = unary_expression_create(NULL);
	s->type = 4;
	s->unary_operator = operator_stack_head();operator_stack_pop();
	s->unary_expression = $2;
	$$=s;
}
;
	
//done
unary_operator
: '+' {printf("unary_operator +\n");
	operator_stack_push(OP_ADD);}
| '-' {printf("unary_operator -\n");
	operator_stack_push(OP_SUB);}
;

//done
multiplicative_expression
: unary_expression {printf("multiplicative_expression unary expression\n");
	struct def_multiplicative_expression * d = multiplicative_expression_create(NULL);
	d->type = 1;
	d->unary_expression = $1;
	$$=d;
}
| multiplicative_expression '*' unary_expression {printf("multiplicative_expression mult_expr * unary_expression\n");
	struct def_multiplicative_expression * d = multiplicative_expression_create(NULL);
	d->type = 2;
	d->multiplicative_expression=$1;
	d->unary_expression = $3;
	$$=d;
}
| multiplicative_expression '|' unary_expression {printf("multiplicative_expression\n");
	struct def_multiplicative_expression * d = multiplicative_expression_create(NULL);
	d->type = 3;
	d->multiplicative_expression=$1;
	d->unary_expression = $3;
	$$=d;
}
;

//done
additive_expression
: multiplicative_expression {printf("additive_expression\n");
	struct def_additive_expression *a = additive_expression_create(NULL);
	a->type = 1;
	a->multiplicative_expression = $1;
	$$=a;
}
| additive_expression '+' multiplicative_expression {printf("additive_expression\n");
	struct def_additive_expression *a = additive_expression_create(NULL);
	a->type = 2;
	a->additive_expression = $1;
	a->multiplicative_expression = $3;
	$$=a;
}
| additive_expression '-' multiplicative_expression {printf("additive_expression\n");
	struct def_additive_expression *a = additive_expression_create(NULL);
	a->type = 3;
	a->additive_expression = $1;
	a->multiplicative_expression = $3;
	$$=a;
}
;

//done
comparison_expression
: additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 1;
	c->additive_expression = $1;
	$$=c;
}
| additive_expression '<' additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 2;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
| additive_expression '>' additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 3;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
| additive_expression LE_OP additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 4;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
| additive_expression GE_OP additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 5;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
| additive_expression EQ_OP additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 6;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
| additive_expression NE_OP additive_expression {printf("comparison_expression\n");
	struct def_comparison_expression * c = comparison_expression_create(NULL);
	c->type = 7;
	c->additive_expression = $1;
	c->additive_expression_2 = $3;
	$$=c;
}
;

//done
expression
: unary_expression assignment_operator comparison_expression {printf("expression\n");
	struct def_expression * e = expression_create(NULL);
	e->type = 1;
	e->unary_expression = $1;
	e->assignment_operator = operator_stack_head();
	e->comparison_expression = $3;
	$$=e;
}
| comparison_expression {printf("expression");
	struct def_expression * e = expression_create(NULL);
	e->type = 2;
	e->comparison_expression = $1;
	$$=e;
}
;

assignment_operator
: '=' {printf("assignment_operator\n");operator_stack_push(OP_EQU);}
| MUL_ASSIGN {printf("assignment_operator\n");operator_stack_push(OP_MUL);}
| ADD_ASSIGN {printf("assignment_operator\n");operator_stack_push(OP_ADD);}
| SUB_ASSIGN {printf("assignment_operator\n");operator_stack_push(OP_SUB);}
;

//done
declaration
: type_name declarator_list ';' {printf("declaration\n");
	
	enum type _type_name_here = type_name_stack_head();
	//type_print(_type_name_here);
	type_name_stack_pop();

	struct def_declaration * d = declaration_create(NULL);
	d->type = 1;
	d->type_name = _type_name_here;
	d->declarator_list = $2;
	declarator_list_print(d->declarator_list);
	struct def_declarator_list * dec = (struct def_declarator_list *)$2;
	//on parcourt la liste de la declaration
	
	while(dec != NULL){
		if(dec->declarator != NULL){
			struct def_declarator * dec2 = dec->declarator;
			//on cree un nouveau symbole;
			struct symbol * s = symbol_create();
			symbol_set_type(s, _type_name_here); //definition de son type
			
			struct array_signature * array = NULL;
			while(dec2 != NULL){
				//si on a declare un tableau, on continue le parcourt :
				//[]
				//[]
				//...
				//identifier
				if(dec2->type == 3 || dec2->type == 4){
					if(_type_name_here != TYPE_FLOAT){
						yyerror("Error trying to declare an array with int type");
						return 1;
					}
					if(array == NULL)
						array = array_create();
					if(dec2->type == 3)
						array_add(array, atoi(dec2->constant));
					else
						array_add(array, 0);
					//on a trouve un tableau
				}else if(dec2->type==1){
					symbol_set_name(s, dec2->identifier);
					printf("\nIDENTIFIER ZERTYUIO -%s-\n",dec2->identifier);
					
					if(temporary_table_has(dec2->identifier) == 1){
						yyerror("symbol already exists");
						return 1;
					}else{
						printf("UNKNOWN CARIABLLIUEJE %s", dec2->identifier);
					}
				}

				//on passe a l'enfant suivant sachant que c'est une criture postfixe
				dec2 = dec2->declarator;
			}
			
			if(array != NULL){
				printf("print tab?\n");
				symbol_set_mode(s, MODE_ARRAY);
				symbol_set_infos(s, array);
				array_print(array);
			}
			declaration_add(d, s);
			temporary_table_add(s);
			d->type = 2;
		}
			
		dec=dec->declarator_list;
	}
	$$=d;}
;

//done
declarator_list
: declarator {printf("declarator_list\n");
	struct def_declarator_list * s = declarator_list_create(NULL);
	s->type = 1;
	s->declarator = $1;
	$$=s;
}
| declarator_list ',' declarator {printf("declarator_list\n");
	struct def_declarator_list * s = declarator_list_create(NULL);
	s->type = 2;
	s->declarator_list = $1;
	s->declarator = $3;
	$$=s;
}
;

type_name
: VOID   {printf("type_name void\n");type_name_stack_push(TYPE_VOID);type_name_stack_print();}
| INT    {printf("type_name int\n");type_name_stack_push(TYPE_INT);type_name_stack_print();}
| FLOAT {printf("type_name float\n");type_name_stack_push(TYPE_FLOAT);type_name_stack_print();}
;

//done
declarator
: IDENTIFIER   {printf("declarator identifier\n");
	struct def_declarator * d = declarator_create(NULL);
	d->type = 1;
	d->identifier = $1;
	$$=d;
}
| '(' declarator ')' {printf("( declarator )\n");
	struct def_declarator * d = declarator_create(NULL);
	d->type = 2;
	d->declarator = $2;
	$$=d;
}
| declarator '[' CONSTANT ']' {printf("declarator [constant]\n");
	struct def_declarator * d =(struct def_declarator *)$1;
	if(!(d->type == 1 || d->type == 3 || d->type==4)){
		yyerror("invalid syntax not a valid array");
		return 1;
	}
	d = declarator_create(NULL);
	d->type = 3;
	d->declarator = $1;
	d->constant = $3;
	$$=d;
}
| declarator '[' ']' {printf("declarator []\n");
	struct def_declarator * d = (struct def_declarator *)$1;
	if(!(d->type == 1 || d->type == 3 || d->type==4)){
		yyerror("invalid syntax not a valid array");
		return 1;
	}
	d = declarator_create(NULL);
	d->type = 4;
	d->declarator = $1;
	$$=d;
}
| declarator '(' parameter_list ')' {printf("declarator (parameter list)\n");
	if(((struct def_declarator *)$1)->declarator != NULL){
		yyerror("invalid syntax");
		return 1;
	}
		
	if(temporary_table_has_function()){
		yyerror("cant' create an other function definition");
		return 1;
	}
	
	//we have found a function declaration, we initialise the temporary table
	//temporary_table_init();
	
	struct def_declarator * d = declarator_create(NULL);
	d->type = 5;
	d->declarator = $1;
	d->parameter_list=$3;
	$$=d;
}
| declarator '(' ')' {printf("declarator ()\n");
	if(((struct def_declarator *)$1)->declarator != NULL){
		yyerror("invalid syntax");
		return 1;
	}

	if(temporary_table_has_function()){
		yyerror("cant' create an other function definition");
		return 1;
	}
	//we have found a function declaration, we initialise the temporary table
	struct symbol * s = symbol_create();
	struct def_declarator * d = declarator_create(NULL);
	d->type = 6;
	d->declarator = $1;
	$$=d;
}
;

//done
parameter_list
: parameter_declaration {printf("parameter_list\n");
	struct def_parameter_list * s = parameter_list_create(NULL);
	s->type = 1;
	s->parameter_declaration = $1;
	$$=s;
}
| parameter_list ',' parameter_declaration {printf("parameter_list\n");
	struct def_parameter_list * s = parameter_list_create(NULL);
	s->type = 2;
	s->parameter_list = $1;
	s->parameter_declaration = $3;
	$$=s;
}
;

//done
parameter_declaration
: type_name declarator {printf("parameter_declaration\n");
	struct def_parameter_declaration * s = parameter_declaration_create(NULL);
	s->type = 1;
	s->type_name = type_name_stack_head();
	type_name_stack_pop();
	s->declarator = $2;
	$$=s;
}
;

//done
statement
: compound_statement {printf("statement\n");
	struct def_statement * s = statement_create(NULL);
	s->type = 1;
	s->compound_statement = $1;
	$$=s;
}
| expression_statement  {printf("statement\n");
	struct def_statement * s = statement_create(NULL);
	s->type = 2;
	s->expression_statement = $1;
	$$=s;
}
| selection_statement {printf("statement\n");
	struct def_statement * s = statement_create(NULL);
	s->type = 3;
	s->selection_statement = $1;
	$$=s;
}
| iteration_statement {printf("statement\n");
	struct def_statement * s = statement_create(NULL);
	s->type = 4;
	s->iteration_statement = $1;
	$$=s;
}
| jump_statement {printf("statement\n");
	struct def_statement * s = statement_create(NULL);
	s->type = 5;
	s->jump_statement = $1;
	$$=s;
}
;

//done
compound_statement
: '{' '}' {printf("compound_statement\n");
	struct def_compound_statement * s = compound_statement_create(NULL);
	s->type = 1;
	$$=s;
}
| '{' statement_list '}' {printf("compound_statement\n");
	struct def_compound_statement * s = compound_statement_create(NULL);
	s->type = 2;
	s->statement_list = $2;
	$$=s;
}
| '{' declaration_list statement_list '}' {printf("compound_statement\n");
	struct def_compound_statement * s = compound_statement_create(NULL);
	s->type = 3;
	s->declaration_list = $2;
	
	//on efface les variables declarees par la structure {}
	int i=0;
	for(;i<s->declaration_list->_count;i++){
		printf("effacement de la variable %s\n",s->declaration_list->_symbols[i]->_name);
		temporary_table_delete(s->declaration_list->_symbols[i]->_name);
	}
	s->statement_list = $3;
	$$=s;
}
;

//done
declaration_list
: declaration {printf("declaration_list\n");
	struct def_declaration_list * s = declaration_list_create(NULL);
	s->type = 1;
	s->declaration = $1;
	
	//compute the declaration_list to retrieve all sub vars !
	s->type = 3;
	declaration_list_compute(s);
	$$ = s;
}
| declaration_list declaration {printf("declaration_list\n");
	struct def_declaration_list * s = declaration_list_create(NULL);
	s->type = 2;
	s->declaration = $2;
	s->declaration_list = $1;

	//compute the declaration_list to retrieve all sub vars !
	s->type = 3;
	declaration_list_compute(s);
	$$ = s;
}
;

//done
statement_list
: statement {printf("statement_list\n");
	struct def_statement_list * s = statement_list_create(NULL);
	s->type = 1;
	s->statement = $1;
	$$ = s;
}
| statement_list statement {printf("statement_list\n");
	struct def_statement_list * s = statement_list_create(NULL);
	s->type = 2;
	s->statement_list = $1;
	s->statement = $2;
	$$ = s;
}
;

//done
expression_statement
: ';' {printf("expression_statement\n");
	struct def_expression_statement * s = expression_statement_create(NULL);
	s->type = 1;
	$$=s;
}
| expression ';' {printf("expression_statement\n");
	struct def_expression_statement *s = expression_statement_create(NULL);
	s->type = 2;
	s->expression = $1;
	$$=s;
}
;

//done
selection_statement
: IF '(' expression ')' statement {printf("selection_statement\n");
	struct def_selection_statement * s = selection_statement_create(NULL);
	s->type = 1;
	s->expression = $3;
	s->statement = $5;
	$$=s;
}
| IF '(' expression ')' statement ELSE statement {printf("selection_statement\n");
	struct def_selection_statement * s = selection_statement_create(NULL);
	s->type = 2;
	s->expression = $3;
	s->statement = $5;
	s->statement_2 = $7;
	$$=s;
}
| FOR '(' expression_statement expression_statement expression ')' statement {printf("selection_statement\n");
	struct def_selection_statement * s = selection_statement_create(NULL);
	s->type = 3;
	s->expression_statement = $3;
	s->expression_statement_2 = $4;
	s->expression = $5;
	s->statement = $7;
	$$=s;
}
;

//done
iteration_statement
: WHILE '(' expression ')' statement {printf("iteration_statement\n");
	struct def_iteration_statement * i = iteration_statement_create(NULL);
	i->type = 1;
	i->expression = $3;
	i->statement = $5;
	$$=i;
}
;

//done
jump_statement
: RETURN ';' {printf("jump_statement\n");
	struct def_jump_statement * s = jump_statement_create(NULL);
	s->type = 1;
	$$=s;
}
| RETURN expression ';' {printf("jump_statement\n");
	struct def_jump_statement * s = jump_statement_create(NULL);
	s->type = 2;
	s->expression = $2;
	$$=s;
}
;

//done
program
: external_declaration {printf("program\n");
	struct def_program * p = program_create(NULL);
	p->type = 1;
	p->external_declaration = $1;
	$$=p;
	
	program_print(p);
	external_table_print();
}
| program external_declaration {printf("program\n");
	struct def_program * p = program_create(NULL);
	p->type = 2;
	p->external_declaration = $2;
	p->program = $1;
	$$=p;
	program_print(p);
	external_table_print();
}
;

//done
external_declaration
: function_definition  {printf("external_declaration\n");
	struct def_external_declaration * p = external_declaration_create(NULL);
	p->type = 1;
	p->function_definition = $1;
	$$=p;
	
}
| declaration {printf("external_declaration\n");
	struct def_external_declaration * p = external_declaration_create(NULL);
	p->type = 2;
	p->declaration = $1;
	$$=p;
	
	struct symbol * _s = NULL;
	int i=0;
	for(;i<p->declaration->_count;i++)
		external_table_add(p->declaration->_symbols[i]);
}
;

//done
function_definition
: type_name declarator compound_statement {printf("function_defintion\n");
	enum type _type_name_here = type_name_stack_head();
	printf("valeur trouve "); type_print(_type_name_here);
	type_name_stack_pop();
	
	struct def_function_definition * f = function_definition_create(NULL);
	f->type = 1;
	f->type_name = _type_name_here;
	f->declarator = $2;
	f->compound_statement = $3;
	$$=f;
	
	struct def_declarator * d = $2;
	if(!(d->type == 5 || d->type ==6)){
		yyerror("Invalid function definition should be ()");
		return 1;
	}
	if(!d->declarator->type == 1){
		yyerror("Invalid function definition should be identifier(...)");
		return 1;
	}
	
	f->name = d->declarator->identifier;
	struct symbol * s = malloc(sizeof(*s));
	symbol_set_name(s, d->declarator->identifier);
	symbol_set_mode(s, MODE_FUNCTION);
	symbol_set_type(s, _type_name_here);
	printf("declarator type lolilolol %d",f->declarator->type);
	if(f->declarator->type == 5 || f->declarator->type == 6){
		//on a liste de parametres, on la parse
		/*
		 parameter_list
		 : parameter_declaration {printf("parameter_list\n");
		 struct def_parameter_list * s = parameter_list_create(NULL);
		 s->type = 1;
		 s->parameter_declaration = $1;
		 $$=s;
		 }
		 | parameter_list ',' parameter_declaration {printf("parameter_list\n");
		 struct def_parameter_list * s = parameter_list_create(NULL);
		 s->type = 2;
		 s->parameter_list = $1;
		 s->parameter_declaration = $3;
		 $$=s;
		 }
		 ;
		 
		 //done
		 parameter_declaration
		 : type_name declarator {printf("parameter_declaration\n");
		 struct def_parameter_declaration * s = parameter_declaration_create(NULL);
		 s->type = 1;
		 s->type_name = type_name_stack_head();
		 type_name_stack_pop();
		 s->declarator = $2;
		 $$=s;
		 }
		 ;		 
		 */
		struct function_signature * f_sign = function_create();
		struct def_parameter_list * param_list = f->declarator->parameter_list;
		while(param_list != NULL){
			//on a un parametre declare
			if(param_list->parameter_declaration != NULL){
				struct def_parameter_declaration * dec2 = param_list->parameter_declaration;
				//on cree un nouveau symbole;
				struct def_declarator * declarator = dec2->declarator;
				struct symbol * stmp = symbol_create();
				symbol_set_type(stmp, dec2->type_name); //definition de son type
				
				//au cas ou on doit declarer un tableau
				struct array_signature * array = NULL;
				while(declarator != NULL){
					if((declarator->type == 5 || declarator->type ==6)){
						yyerror("Invalid no function definition in function parameters");
						return 1;
					}
					if(declarator->type == TYPE_VOID){
						yyerror("trying to declare a void typed parameter");
						return 1;
					}
					//si on a declare un tableau, on continue le parcourt :
					//[]
					//[]
					//...
					//identifier
					if(declarator->type == 3 || declarator->type == 4){
						if(dec2->type_name != TYPE_FLOAT){
							yyerror("Error trying to declare an array with int type");
							return 1;
						}
						if(array == NULL)
							array = array_create();
						if(dec2->type == 3)
							array_add(array, atoi(declarator->constant));
						else
							array_add(array, 0);
						//on a trouve un tableau
					}else if(declarator->type==1){
						//on definit l'identifiant du symbole courant
						symbol_set_name(stmp, declarator->identifier);
						if(temporary_table_has(declarator->identifier) == 1){
							yyerror("symbol already exists in external table, firs declared here !");
							return 1;
						}
					}else{
						yyerror("invalid variable definition");
						return 1;
					}
					
					//on passe a l'enfant suivant sachant que c'est une criture postfixe
					declarator = declarator->declarator;
				}
				
				//on a finit de parcourir, on a soit un tableau soit une variable
				if(array != NULL){
					printf("print tab?\n");
					symbol_set_mode(stmp, MODE_ARRAY);
					symbol_set_infos(stmp, array);
					array_print(array);
				}
				function_add_symbol(f_sign, stmp);
				printf("AZERTYUIOPOIUYTREZAZERTYUIOIUYTRESQSI\n");
				temporary_table_add(stmp);
			}
			
			//on passe dans la liste et donc potentiellement dans le prochain parametre
			//vers la gauche
			param_list=param_list->parameter_list;
		}
		function_print_signature(f_sign);
		printf("???????");
		symbol_set_mode(s, MODE_FUNCTION);
		symbol_set_infos(s,f_sign);
	}
	printf("TOTOTOTOTOTOTOTOTOTOTOTOOTT %s", s->_name);

	if(temporary_table_has(s->_name)){
		char * ff = malloc((50+strlen(s->_name)+1)*sizeof(char));
		sprintf(ff,"Var %s already defined here",s->_name);
		yyerror(ff);
		free(ff);
		return 1;
	}
	external_table_add(s);
	//on flush la table pour permettre a d'autres de créer ensuite leur table
	temporary_table_print();

	temporary_table_deinit();
	temporary_table_init();
	f->signature = s;
	f->type = 2;
	}
;

%%
#include <stdio.h>
#include <string.h>
#include "type_name_stack.h"
#include "operator_stack.h"

extern char yytext[];
extern int column;
extern int yylineno;
extern FILE *yyin;

char *file_name = NULL;

int yyerror (char *s) {
	fflush (stdout);
	fprintf (stderr, "%s:%d:%d: %s\n", file_name, yylineno, column, s);
	return 0;
}


int main (int argc, char *argv[]) {
	type_name_stack_init();
	operator_stack_init();
	
	
	//initialisation de la table des symboles !
	//dans ce systeme on ne peut avoir qu'au maximum deux tables de symboles avec la table temporaire et la table extern
	//on ne compte pas les tables contruites apres passages
	// > la fonction actuelle et la table des symboles globale
	temporary_table_init();
	external_table_init();

	FILE *input = NULL;
	if (argc==2) {
		input = fopen (argv[1], "r");
		file_name = strdup (argv[1]);
		if (input) {
	    yyin = input;
		}
		else {
	    fprintf (stderr, "Could not open %s\n", argv[1]);
	    return 1;
		}
	}
	else {
		fprintf (stderr, "%s: error: no input file\n", *argv);
		return 1;
	}
	yyparse ();
	
	
	free (file_name);
	return 0;
}